home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / tcqb.arc / QUICKB.C < prev    next >
Encoding:
C/C++ Source or Header  |  1988-02-29  |  20.9 KB  |  1,038 lines

  1. #pragma inline
  2.  
  3. /*
  4.    QUICKB.C - Quick B Protocol Support routines
  5.  
  6.      originally converted to C by Paul M. Resch
  7.     heavly modified by John Bridges
  8.  */
  9.  
  10. /*
  11.   This module implements the B-Protocol Functions.
  12.  
  13.   bp_DLE should be invoked whenever a <DLE> is received.
  14.   bp_ENQ should be called whenever an <ENQ> is received.
  15.  
  16.   cgetc is an external procedure which returns a character from the
  17.      communications port or -1 if no character is received within the time
  18.      specified (in tenths of seconds).
  19.   cputc is an external procedure which sends a character to the communication
  20.      port.
  21.   create is an external procedure which creates the named file.
  22.   open is an external procedure which opens the named file for input, and
  23.      returns a handle for the file.
  24.   close is an external procedure which closes the file specified by handle.
  25.   read is an external procedure which reads the specified number of bytes
  26.      from the file specified by handle, and returns the number of bytes
  27.      actually read, or a negative error.
  28.   write is an external procedure which writes the specified number of bytes
  29.      to the file specified by handle.
  30.   user_abort is an external procedure which is TRUE if the user wants to stop.
  31.  
  32.   This source was originally derived from QUICKB.INC, version 121687, written
  33.   by Russ Ranshaw, CompuServe Incorporated.
  34.  
  35.  */
  36.  
  37. #define    TRUE    1
  38. #define    FALSE    0
  39.  
  40. #define    DLE        16
  41. #define    ETX        03
  42. #define    NAK        21
  43. #define    ENQ        05
  44. #define    CR        0x0D
  45. #define    LF        0x0A
  46. #define    MAX_BUF_SIZE    1032        /* Largest data block we can handle */
  47. #define    MAX_SA        2        /* Maximum number of waiting packets */
  48.  
  49. #define    DEF_BUF_SIZE    511        /* Default data block */
  50. #define    DEF_WS        1        /* I can send 2 packets ahead */
  51. #define    DEF_WR        1        /* I can receive single send-ahead */
  52. #define    DEF_BS        8        /* I can handle 1024 bytes */
  53. #define    DEF_CM        1        /* I can handle CRC */
  54. #define    DEF_DQ        1        /* I can handle non-quoted NUL */
  55.  
  56. #define    MAX_ERRORS    10
  57.  
  58.  
  59. /* Receive states */
  60.  
  61. #define    R_GET_DLE    0
  62. #define    R_GET_B        1
  63. #define    R_GET_SEQ    2
  64. #define    R_GET_DATA    3
  65. #define    R_GET_CHECKSUM    4
  66. #define    R_SEND_ACK    5
  67. #define    R_TIMED_OUT    6
  68. #define    R_SUCCESS    7
  69.  
  70. /* Send states */
  71.  
  72. #define    S_GET_DLE    1
  73. #define    S_GET_NUM    2
  74. #define    S_HAVE_ACK    3
  75. #define    S_GET_PACKET    4
  76. #define    S_TIMED_OUT    5
  77. #define    S_SEND_NAK    6
  78. #define    S_SEND_ENQ    7
  79. #define    S_SEND_DATA    8
  80.  
  81. typedef    struct    PACKETB {
  82.     int seq;    /* Packet's sequence number */
  83.     int num;    /* Number of bytes in packet */
  84.     unsigned char buf[MAX_BUF_SIZE]; /* Actual packet data */
  85.     } PACKET;
  86.  
  87. static PACKET    SA_Buf[MAX_SA+1];  /* Send-ahead buffers */
  88.  
  89. /* Table of control characters that need to be masked */
  90.  
  91. static char mask_table[]={
  92.         0, 0, 0, 1, 0, 1, 0, 0,    /* NUL SOH SOB ETX EOT ENQ SYN BEL */
  93.         0, 0, 0, 0, 0, 0, 0, 0,    /* BS  HT  LF  VT  FF  CR  SO  SI */
  94.         1, 1, 0, 1, 0, 1, 0, 0,    /* DLE DC1 DC2 DC3 DC4 NAK ^V  ^W */
  95.         0, 0, 0, 0, 0, 0, 0, 0};  /* CAN ^Y  ^Z  ESC ?    ?    ?    ? */
  96.  
  97. static char hex_digit[]="0123456789ABCDEF";
  98.  
  99. unsigned int checksum;        /* May hold CRC */
  100. static int seq_num;        /* Current Sequence Number - init by Term_ENQ */
  101. static int r_size;        /* size of receiver buffer */
  102. static unsigned int s_counter,r_counter;
  103. static int timed_out;        /* we timed out before receiving character */
  104. static int cchar;        /* current character */
  105. static int masked;        /* TRUE if ctrl character was 'masked' */
  106. static int packet_received;    /* True if a packet was received */
  107. static unsigned char r_buffer[MAX_BUF_SIZE];
  108.  
  109.     /* Other End's Parameters */
  110. static char His_WS;        /* Sender's Window Send */
  111. static char His_WR;        /* Sender's Window Receive */
  112. static char His_BS;        /* Sender's Block Size */
  113. static char His_CM;        /* Sender's Check Method */
  114.  
  115.     /* Negotiated Parameters */
  116. static char Our_WS;        /* Negotiated Window Send */
  117. static char Our_WR;        /* Negotiated Window Receive */
  118. static char Our_BS;        /* Negotiated Block Size */
  119. static char Our_CM;        /* Negotiated Check Method */
  120.  
  121. static int Quick_B;        /* True if Quick B in effect */
  122. static int Use_CRC;        /* True if CRC in effect */
  123. static int buffer_size;        /* Our_BS * 4 */
  124. static int SA_Max;        /* 1 if SA not enabled, else MAX_SA */
  125. static int SA_Enabled;        /* True if Send-Ahead is permitted */
  126. static int ack_SA;        /* Which SA_Buf is waiting for an ACK */
  127. static int fill_SA;        /* Which SA_Buf is ready for new data */
  128. static int SA_Waiting;        /* Number of SA_Buf's waiting for ACK */
  129. static int Aborting;        /* TRUE if aborting transfer */
  130.  
  131. extern long lseek(int fs,long pos,int mode);
  132.  
  133. /* Update the checksum/CRC */
  134.  
  135. static void do_checksum(chr)
  136. unsigned char chr;
  137. {
  138.     if(Quick_B && Use_CRC)
  139.         checksum=upd_CRC(chr);
  140.     else
  141.     {
  142.         asm mov al,byte ptr checksum
  143.         asm rol al,1
  144.         asm add al,chr
  145.         asm adc al,0
  146.         asm mov byte ptr checksum,al
  147.     }
  148. }
  149.  
  150. static void send_failure(code)
  151. int code;
  152. {
  153.     register PACKET    *p;
  154.  
  155.     ack_SA=0;
  156.     fill_SA=0;
  157.     SA_Waiting=0;
  158.     Aborting=TRUE;        /* inform get_ACK we're aborting */
  159.  
  160.     p=&SA_Buf[0];
  161.     p->buf[0]='F';
  162.     p->buf[1]=code;
  163.  
  164.     if(send_packet(1))
  165.         SA_Flush();    /* Gotta wait for the host to ACK it */
  166. }
  167.  
  168. /*
  169.  * bp_ENQ is called when the terminal emulator receives the character <ENQ>
  170.  * from the host.  Its purpose is to initialize for B Protocol and tell the
  171.  * host that we support Quick B.
  172.  */
  173.  
  174. void bp_ENQ()
  175. {
  176.     seq_num=0;
  177.     buffer_size=DEF_BUF_SIZE;    /* Set up defaults */
  178.     Quick_B=FALSE;            /* Not Quick B Protocol */
  179.     Use_CRC=FALSE;            /* Not CRC_16 */
  180.     SA_Enabled=FALSE;        /* No Send-Ahead by us */
  181.     SA_Max=1;            /* single packet sent */
  182.  
  183.     cputc(DLE);
  184.     cputc('+');
  185.  
  186.     cputc(DLE);
  187.     cputc('0');
  188. }
  189.  
  190. static void send_masked_byte(c)
  191. int c;
  192. {
  193.     c&=0xff;
  194.     if(c<32)
  195.     {
  196.         if(mask_table[c]!=0)
  197.         {
  198.             cputc(DLE);
  199.             cputc(c+'@');
  200.         }
  201.         else
  202.             cputc(c);
  203.     }
  204.     else
  205.         cputc(c);
  206.  
  207.     s_counter=(s_counter+1)&DEF_BUF_SIZE;
  208. }
  209.  
  210. static void send_ack()
  211. {
  212.     cputc(DLE);
  213.     cputc(seq_num + '0');
  214. }
  215.  
  216. static void send_nak()
  217. {
  218.     cputc(NAK);
  219. }
  220.  
  221.  
  222. static void send_enq()
  223. {
  224.     cputc(ENQ);
  225. }
  226.  
  227. static int read_byte()
  228. {
  229.     timed_out=FALSE;
  230.  
  231.     cchar=cgetc(100);
  232.  
  233.     if(cchar < 0)
  234.         return(FALSE);
  235.  
  236.     r_counter=(r_counter+1)&DEF_BUF_SIZE;
  237.     return(TRUE);
  238. }
  239.  
  240.  
  241. static int read_masked_byte()
  242. {
  243.     masked=FALSE;
  244.  
  245.     if(read_byte()==FALSE)
  246.         return(FALSE);
  247.  
  248.     if(cchar==DLE)
  249.     {
  250.         if(read_byte()==FALSE)
  251.             return(FALSE);
  252.         cchar &=0x1F;
  253.         masked=TRUE;
  254.     }
  255.  
  256.     return(TRUE);
  257. }
  258.  
  259. /* Increment Sequence Number */
  260.  
  261. static int incr_seq(value)
  262. int value;
  263. {
  264.     return(value==9 ? 0 : value + 1);
  265. }
  266.  
  267. /*    Lead_in_Seen is TRUE if the <DLE><B> has been seen already.
  268.     from_send_packet is TRUE if called from Send_Packet
  269.     (causes exit on first error detected)
  270.     Returns True if packet is available from host. */
  271.  
  272. static int read_packet(lead_in_seen,from_send_packet)
  273. int lead_in_seen,from_send_packet;
  274. {
  275.     int state,next_seq,block_num,errors,new_cks;
  276.     int i;
  277.  
  278.     packet_received=FALSE;
  279.     for(i=0; i<buffer_size; i++)
  280.         r_buffer[i]=0;
  281.     next_seq=(seq_num+1)%10;
  282.     errors=0;
  283.  
  284.     if(lead_in_seen)        /* Start off on the correct foot */
  285.         state=R_GET_SEQ;
  286.     else
  287.         state=R_GET_DLE;
  288.  
  289.     while(TRUE)
  290.     {
  291.         switch (state){
  292.         case R_GET_DLE :
  293.             if(user_abort())
  294.             {
  295.                 send_failure('A');
  296.                 return(FALSE);
  297.             }
  298.  
  299.             if(!read_byte())
  300.                     state=R_TIMED_OUT;
  301.             else if((cchar & 0x7F)==DLE)
  302.                     state=R_GET_B;
  303.             else if((cchar & 0x7F)==ENQ)
  304.                 state=R_SEND_ACK;
  305.             break;
  306.  
  307.         case R_GET_B :
  308.             if(!read_byte())
  309.                 state=R_TIMED_OUT;
  310.             else if((cchar & 0x7F)=='B')
  311.                 state=R_GET_SEQ;
  312.             else if(cchar==ENQ)
  313.                 state=R_SEND_ACK;
  314.             else
  315.                 state=R_GET_DLE;
  316.             break;
  317.  
  318.         case R_GET_SEQ :
  319.             if(!read_byte())
  320.                 state=R_TIMED_OUT;
  321.             else if(cchar==ENQ)
  322.                 state=R_SEND_ACK;
  323.             else
  324.             {
  325.                 if(Quick_B && Use_CRC)
  326.                     checksum=init_CRC(-1);
  327.                 else checksum=0;
  328.  
  329.                 block_num=cchar - '0';
  330.  
  331.                 do_checksum(cchar);
  332.  
  333.                 i=0;
  334.                 state=R_GET_DATA;
  335.             }
  336.             break;
  337.  
  338.         case R_GET_DATA :
  339.             r_counter=0;
  340.             if(!read_masked_byte())
  341.                 state=R_TIMED_OUT;
  342.             else if((cchar==ETX)&& !masked)
  343.             {
  344.                 do_checksum(ETX);
  345.                 state=R_GET_CHECKSUM;
  346.             }
  347.             else
  348.             {
  349.                 r_buffer[i]=cchar;
  350.                 i=i + 1;
  351.                 do_checksum(cchar);
  352.             }
  353.             break;
  354.  
  355.         case R_GET_CHECKSUM :
  356.             if(!read_masked_byte())
  357.                 state=R_TIMED_OUT;
  358.             else
  359.             {
  360.                 if(Quick_B && Use_CRC)
  361.                 {
  362.                     checksum=upd_CRC(cchar);
  363.  
  364.                     if(!read_masked_byte())
  365.                         new_cks=checksum ^ 0xFF;
  366.                     else
  367.                     {
  368.                         checksum=upd_CRC(cchar);
  369.                         new_cks=0;
  370.                     }
  371.                 }
  372.                 else new_cks=cchar;
  373.  
  374.                 if(new_cks !=checksum)
  375.                     state=R_TIMED_OUT;
  376.                 else if(r_buffer[0]=='F')/* Watch for Failure Packet */
  377.                     state=R_SUCCESS;    /* which is accepted regardless */
  378.                 else if(block_num==seq_num)    /* Watch for duplicate block */
  379.                     state=R_SEND_ACK;
  380.                 else if(block_num !=next_seq)
  381.                     state=R_TIMED_OUT;    /* Bad sequence number */
  382.                 else
  383.                     state=R_SUCCESS;
  384.             }
  385.             break;
  386.  
  387.         case R_TIMED_OUT :
  388.             errors=errors + 1;
  389.  
  390.             if((errors > MAX_ERRORS)||(from_send_packet))
  391.                 return(FALSE);
  392.  
  393.             send_nak();
  394.  
  395.             if(from_send_packet)
  396.                 return(FALSE);
  397.  
  398.             state=R_GET_DLE;
  399.             break;
  400.  
  401.         case R_SEND_ACK :
  402.             send_ack();
  403.             state=R_GET_DLE;    /* wait for the next block */
  404.             break;
  405.  
  406.         case R_SUCCESS :
  407.             seq_num=block_num;
  408.             r_size=i;
  409.             packet_received=TRUE;
  410.             return(TRUE);
  411.         }
  412.     }
  413. }
  414.  
  415. static void send_data(Buffer_Number)
  416. int Buffer_Number;
  417. {
  418.     int i;
  419.     register PACKET    *p;
  420.  
  421.     s_counter=0;
  422.     p=&SA_Buf[Buffer_Number];
  423.     if(Quick_B && Use_CRC)
  424.         checksum=init_CRC(-1);
  425.     else
  426.         checksum=0;
  427.  
  428.     cputc(DLE);
  429.     cputc('B');
  430.  
  431.     cputc(p->seq + '0');
  432.     do_checksum(p->seq + '0');
  433.  
  434.     for(i=0; i<=p->num; i++)
  435.     {
  436.         send_masked_byte(p->buf[i]);
  437.         do_checksum(p->buf[i]);
  438.     }
  439.  
  440.     cputc(ETX);
  441.     do_checksum(ETX);
  442.  
  443.     if(Quick_B && Use_CRC)
  444.         send_masked_byte(checksum >> 8);
  445.  
  446.     send_masked_byte(checksum);
  447. }
  448.  
  449. static int incr_SA(old_value)
  450. int old_value;
  451. {
  452.     return(old_value==MAX_SA ? 0 : old_value + 1);
  453. }
  454.  
  455. /*
  456.  * ReSync is called to restablish syncronism with the remote.  This is
  457.  * accomplished by sending <ENQ><ENQ> and waiting for the sequence
  458.  * <DLE><d><DLE><d> to be received, ignoring everything else.
  459.  *
  460.  * Return is -1 on time out, else the digit <d>.
  461.  */
  462. #define    GET_FIRST_DLE        1
  463. #define    GET_FIRST_DIGIT        2
  464. #define    GET_SECOND_DLE        3
  465. #define    GET_SECOND_DIGIT    4
  466.  
  467. static int ReSync()
  468. {
  469.     int state,Digit_1;
  470.  
  471.     cputc(ENQ);    /* Send <ENQ><ENQ> */
  472.     cputc(ENQ);
  473.     state=GET_FIRST_DLE;
  474.  
  475.     while(1)
  476.     {
  477.         switch(state){
  478.         case GET_FIRST_DLE :
  479.             if(!read_byte())
  480.                 return(-1);
  481.             if(cchar==DLE)
  482.                 state=GET_FIRST_DIGIT;
  483.             break;
  484.         case GET_FIRST_DIGIT :
  485.             if(!read_byte())
  486.                 return(-1);
  487.             if((cchar >='0')&&(cchar <='9'))
  488.             {
  489.                 Digit_1=cchar;
  490.                 state=GET_SECOND_DLE;
  491.             }
  492.             break;
  493.         case GET_SECOND_DLE :
  494.             if(!read_byte())
  495.                 return(-1);
  496.             if(cchar==DLE)
  497.                 state=GET_SECOND_DIGIT;
  498.             break;
  499.         case GET_SECOND_DIGIT :
  500.             if(!read_byte())
  501.                 return(-1);
  502.             if((cchar >='0')&&(cchar <='9'))
  503.             {
  504.                 if(Digit_1==cchar)
  505.                     return(cchar);
  506.                 else
  507.                 {
  508.                     Digit_1=cchar;
  509.                     state=GET_SECOND_DLE;
  510.                 }
  511.             }
  512.             else
  513.                 state=GET_SECOND_DLE;
  514.             break;
  515.         }
  516.     }
  517. }
  518.  
  519. /*
  520.  * get_ACK is called to wait until the SA_Buf indicated by ack_SA
  521.  * has been ACKed by the host.
  522.  */
  523. static int get_ACK()
  524. {
  525.     int state,errors,block_num,i;
  526.     int Sent_ENQ;
  527.     int SA_Index;
  528.  
  529.     packet_received=FALSE;
  530.     errors=0;
  531.     Sent_ENQ=FALSE;
  532.     state=S_GET_DLE;
  533.  
  534.     while(TRUE)
  535.     {
  536.         switch(state){
  537.         case S_GET_DLE :
  538.             if(user_abort())
  539.             {
  540.                 send_failure('A');
  541.                 return(FALSE);
  542.             }
  543.  
  544.             if(!read_byte())
  545.                 state=S_TIMED_OUT;
  546.             else if(cchar==DLE)
  547.                 state=S_GET_NUM;
  548.             else if(cchar==NAK)
  549.             {
  550.                 if(++errors > MAX_ERRORS)
  551.                     return(FALSE);
  552.                 state=S_SEND_ENQ;
  553.             }
  554.             else if(cchar==ETX)
  555.                 state=S_SEND_NAK;
  556.             break;
  557.  
  558.         case S_GET_NUM :
  559.             if(!read_byte())
  560.                 state=S_TIMED_OUT;
  561.             else if((cchar >='0')&&(cchar <='9'))
  562.                 state=S_HAVE_ACK;    /* Received ACK */
  563.             else if(cchar=='B')
  564.                 state=S_GET_PACKET; /* Try to get packet */
  565.             else if(cchar==NAK)
  566.             {
  567.                 if(++errors > MAX_ERRORS)
  568.                     return(FALSE);
  569.                 state=S_SEND_ENQ;
  570.             }
  571.             else
  572.                 state=S_TIMED_OUT;
  573.             break;
  574.  
  575.         case S_GET_PACKET :
  576.             if(read_packet(TRUE,TRUE))
  577.             {
  578.                 if(r_buffer[0]=='F')
  579.                 {
  580.                     send_ack();
  581.                     return(FALSE);
  582.                 }
  583.                 else
  584.                     return(TRUE);
  585.             }
  586.  
  587.             state=S_TIMED_OUT; /* On a bad receive, try again */
  588.             break;
  589.         case S_HAVE_ACK:
  590.             block_num=cchar - '0';
  591.             if(SA_Buf[ack_SA].seq==block_num)
  592.             {    /* This is the one we're waiting for */
  593.                 ack_SA=incr_SA(ack_SA);
  594.                 SA_Waiting--;
  595.                 return(TRUE);
  596.             }
  597.             else if(SA_Buf[incr_SA(ack_SA)].seq==block_num &&
  598.                 (SA_Waiting==2))
  599.             {    /* Must have missed an ACK */
  600.                 ack_SA=incr_SA(ack_SA);
  601.                 ack_SA=incr_SA(ack_SA);
  602.                 SA_Waiting -=2;
  603.                 return(TRUE);
  604.             }
  605.             else if(SA_Buf[ack_SA].seq==incr_seq(block_num))
  606.             {
  607.                 if(Sent_ENQ)
  608.                     state=S_SEND_DATA;
  609.                 else
  610.                     state=S_GET_DLE;
  611.             }
  612.             else
  613.                 state=Aborting ? S_GET_DLE : S_TIMED_OUT;
  614.             Sent_ENQ=FALSE;
  615.             break;
  616.         case S_TIMED_OUT :
  617.             if(++errors > MAX_ERRORS)
  618.                 return(FALSE);
  619.             else
  620.             {
  621.                 if(Aborting &&(errors > 3))
  622.                     return(FALSE);
  623.             }
  624.             state=S_SEND_ENQ;
  625.             break;
  626.  
  627.         case S_SEND_NAK :
  628.             if(++errors > MAX_ERRORS)
  629.                 return(FALSE);
  630.  
  631.             send_nak();
  632.  
  633.             state=S_GET_DLE;
  634.             break;
  635.  
  636.         case S_SEND_ENQ :
  637.             if(++errors > MAX_ERRORS)
  638.                 return(FALSE);
  639.             cchar=ReSync();
  640.             if(cchar==-1)
  641.                 state=S_SEND_ENQ;
  642.             else
  643.                 state=S_HAVE_ACK;
  644.             Sent_ENQ=TRUE;
  645.             break;
  646.  
  647.         case S_SEND_DATA :
  648.             SA_Index=ack_SA;
  649.  
  650.             for(i=1; i<=SA_Waiting; i++)
  651.             {
  652.                 send_data(SA_Index);
  653.                 SA_Index=incr_SA(SA_Index);
  654.             }
  655.  
  656.             state=S_GET_DLE;
  657.             Sent_ENQ=FALSE;
  658.             break;
  659.         }
  660.     }
  661. } /* get_ACK */
  662.  
  663. static int send_packet(size)
  664. int size;
  665. {
  666.     if(SA_Waiting==SA_Max)
  667.         if(!get_ACK())
  668.             return(FALSE);
  669.  
  670.     seq_num=incr_seq(seq_num);
  671.     SA_Buf[fill_SA].seq=seq_num;
  672.     SA_Buf[fill_SA].num=size;
  673.     send_data(fill_SA);
  674.     fill_SA=incr_SA(fill_SA);
  675.     SA_Waiting=SA_Waiting + 1;
  676.     return(TRUE);
  677. }
  678. /*
  679.  * SA_Flush is called after sending the last packet to get host's
  680.  * ACKs on outstanding packets.
  681.  */
  682. static int SA_Flush()
  683. {
  684.     while(SA_Waiting > 0)
  685.         if(!get_ACK())
  686.             return(FALSE);
  687.     return(TRUE);
  688. }
  689.  
  690. #define tval (*(unsigned long far *)0x0040006cl)
  691.  
  692. /* Send_File is called to send a file to the host */
  693. static int send_file(name)
  694. char name[];
  695. {
  696.     int fd,bknum,cps,n;
  697.     long oldt,pos;
  698.     unsigned long filelen;
  699.     register PACKET    *p;
  700.  
  701.     sput("Sending \"");
  702.     sput(name);
  703.     sput("\"\r\n");
  704.  
  705.     fd=open(name);
  706.     if(fd<=0)
  707.       {
  708.         sput("\r\n** Cannot find that file **\r\n");
  709.         send_failure('E');
  710.         return(FALSE);
  711.     }
  712.  
  713.     filelen=lseek(fd,0l,2);
  714.     lseek(fd,0l,0);
  715.  
  716.     oldt=tval;
  717.     bknum=1;
  718.     sput("\r\n");
  719.     do
  720.     {
  721.         p=&SA_Buf[fill_SA];
  722.         p->buf[0]='N';
  723.         n=read(fd,(long)buffer_size,&p->buf[1]);
  724.         if(n>0)
  725.         {
  726.             sput("Block #");
  727.             putint(bknum,4);
  728.             sput(", ");
  729.             if(send_packet(n)==FALSE)
  730.                 return(FALSE);
  731.             ++bknum;
  732.             pos=lseek(fd,0l,1);
  733.             putlint(pos,9);
  734.             sput(" Bytes, at ");
  735.             if(tval<oldt)
  736.                 oldt-=1573040l;
  737.             cps=((pos*4661l)/(tval-oldt))>>8;
  738.             putint(cps,4);
  739.             sput("cps ");
  740.             putint((int)((100*pos)/filelen),3);
  741.             sput("% Complete\r");
  742.         }
  743.     } while(n==buffer_size);
  744.  
  745.     close(fd);
  746.  
  747.     if(n < 0)
  748.     {
  749.         send_failure('E');
  750.         sput("\r\n** Read failure...aborting **\r\n");
  751.         return(FALSE);
  752.     }
  753.  
  754. /* Inform host that the file was sent */
  755.     p=&SA_Buf[fill_SA];
  756.     p->buf[0]='T';
  757.     p->buf[1]='C';
  758.  
  759.     if(send_packet(2)==FALSE)
  760.         return(FALSE);
  761.     else
  762.     {
  763.         sput("\r\nWaiting for host...\r\n");
  764.         if(!SA_Flush())
  765.             return(FALSE);
  766.         return(TRUE);
  767.     }
  768. }
  769.  
  770. /*
  771.  * do_transport_parameters is called when a Packet type of + is received.
  772.  * It sends a packet of our local Quick B parameters and sets the Our_xx
  773.  * parameters to the minimum of the sender's and our own parameters.
  774.  */
  775. static do_transport_parameters()
  776. {
  777.     register PACKET    *p;
  778.  
  779.     His_WS=r_buffer[1];    /* Pick out Sender's parameters */
  780.     His_WR=r_buffer[2];
  781.     His_BS=r_buffer[3];
  782.     His_CM=r_buffer[4];
  783.  
  784.     p=&SA_Buf[fill_SA];
  785.     p->buf[0]='+';  /* Prepare to return our own parameters */
  786.     p->buf[1]=DEF_WS;
  787.     p->buf[2]=DEF_WR;
  788.     p->buf[3]=DEF_BS;
  789.     p->buf[4]=DEF_CM;
  790.     p->buf[5]=DEF_DQ;
  791.  
  792.     if(!send_packet(5))
  793.         return;
  794.  
  795.     if(SA_Flush())        /* Wait for host's ACK on our packet */
  796.     {
  797. /* Take minimal subset of Transport Params. */
  798. /* If he can send ahead, we can receive it. */
  799.         Our_WR=(His_WS < DEF_WR)? His_WS : DEF_WR;
  800.  
  801. /* If he can receive send ahead, we can send it. */
  802.         Our_WS=(His_WR < DEF_WS)? His_WR : DEF_WS;
  803.  
  804.         Our_BS=His_BS < DEF_BS ? His_BS : DEF_BS;
  805.  
  806.         Our_CM=His_CM < DEF_CM ? His_CM : DEF_CM;
  807.  
  808.         if(Our_BS==0)
  809.             Our_BS=4;    /* Default */
  810.  
  811.         buffer_size=Our_BS * 128;
  812.  
  813.         Quick_B=TRUE;
  814.  
  815.         if(Our_CM==1)
  816.             Use_CRC=TRUE;
  817.  
  818.         if(Our_WS !=0)
  819.         {
  820.             SA_Enabled=TRUE;
  821.             SA_Max=MAX_SA;
  822.         }
  823.     }
  824. }
  825.  
  826. /*
  827.   do_application_parameters is called when a ? packet is received.
  828.   This version ignores the host's packet and returns a ? packet
  829.   saying that normal B Protocol File Transfer is supported.
  830.  (Well, actually it says that no extended application packets are
  831.     supported.  The T packet is assumed to be standard.)*/
  832.  
  833. static void do_application_parameters()
  834. {
  835.     register PACKET    *p;
  836.  
  837.     p=&SA_Buf[fill_SA];
  838.     p->buf[0]='?';    /* Build the ? packet */
  839.     p->buf[1]=1;        /* The T packet flag */
  840.  
  841.     if(send_packet(1))        /* Send the packet */
  842.         SA_Flush();
  843. }
  844.  
  845. /* Receive_File is called to receive a file from the host */
  846. static int receive_file(name)
  847. char name[];
  848. {
  849.     int fd,bknum,cps;
  850.     long oldt,pos;
  851.     long bytes;
  852.  
  853.     sput("Receiving \"");
  854.     sput(name);
  855.     sput("\"\r\n");
  856.  
  857.     fd=create(name);
  858.     if(fd<=0)
  859.     {
  860.         sput("\r\n** Cannot open file...aborting **\r\n");
  861.         send_failure('E');
  862.         return(FALSE);
  863.     }
  864.  
  865.     sput("\r\n");
  866.     send_ack();
  867.  
  868.     oldt=tval;
  869.     bknum=1;
  870.  
  871. /* Process each incoming packet until 'TC' packet received or failure */
  872.     while(TRUE)
  873.     {
  874.         sput("Block #");
  875.         putint(bknum,4);
  876.         sput(", ");
  877.         if(read_packet(FALSE,FALSE))
  878.         {
  879.             switch(r_buffer[0])
  880.             {
  881.             case 'N' :
  882.                 bytes=r_size - 1;
  883.                 if(write(fd,bytes,&r_buffer[1])!=bytes)
  884.                 {
  885.                     sput("\r\n** Write failure...aborting **\r\n");
  886.                     close(fd);
  887.                     send_failure('E');
  888.                     return(FALSE);
  889.                 }
  890.                 send_ack();
  891.                 ++bknum;
  892.                 pos=lseek(fd,0l,1);
  893.                 putlint(pos,9);
  894.                 sput(" Bytes, at ");
  895.                 if(tval<oldt)
  896.                     oldt-=1573040l;
  897.                 cps=((pos*4661l)/(tval-oldt))>>8;
  898.                 putint(cps,4);
  899.                 sput("cps\r");
  900.                 break;
  901.  
  902.             case 'T' :
  903.                 if(r_buffer[1]=='C')
  904.                 {
  905.                     close(fd);
  906.  
  907.                     send_ack();
  908.                     return(TRUE);
  909.                 }
  910.                 else
  911.                 {
  912.                     sput("\r\n** Invalid termination packet...aborting **\r\n");
  913.                     close(fd);
  914.                     send_failure('N');
  915.                     return(FALSE);
  916.                 }
  917.  
  918.             case 'F' :
  919.                 send_ack();
  920.                 sput("\r\n** Failure packet received...aborting **\r\n");
  921.                 close(fd);
  922.                 return(FALSE);
  923.             }
  924.         }
  925.         else
  926.         {
  927.             sput("\r\n** Failed to receive packet...aborting **\r\n");
  928.             close(fd);
  929.             return(FALSE);
  930.         }
  931.     }
  932. }
  933.  
  934. /*
  935.  * bp_DLE is called from the main program when the character <DLE> is
  936.  * received from the host.
  937.  *
  938.  * This routine calls read_packet and dispatches to the appropriate
  939.  * handler for the incoming packet.
  940.  */
  941. void bp_DLE()
  942. {
  943.     int i;
  944.     char filename[255];
  945.     char *pt;
  946. /*
  947.  * Begin by getting the next character.  If it is <B> then enter the
  948.  * B_Protocol state.  Otherwise simply return.
  949.  */
  950.  
  951.     if(cgetc(10)!='B')
  952.         return;
  953.  
  954.     ack_SA=0;    /* Initialize Send-ahead variables */
  955.     fill_SA=0;
  956.     SA_Waiting=0;
  957.     Aborting=FALSE;    /* not aborting ... yet */
  958. /*  <DLE><B> received; begin B Protocol */
  959.  
  960.     r_counter=0;
  961.     s_counter=0;
  962.  
  963.     sput("\r\n");
  964.     if(Quick_B)
  965.     {
  966.         sput("*** Quick B is in effect ***\r\n");
  967.  
  968.         if(Use_CRC)
  969.             sput("*** Using CRC ***\r\n");
  970.  
  971.         if(Our_WS!=0)    /* Allow send-ahead if other end agrees */
  972.             sput("*** Send-Ahead enabled ***\r\n");
  973.     }
  974.  
  975.     if(read_packet(TRUE,FALSE))
  976.     {
  977. /* Dispatch on the type of packet just received */
  978.  
  979.         switch(r_buffer[0])
  980.         {
  981.         case 'T':    /* File Transfer Application */
  982.             switch(r_buffer[1])
  983.             {
  984.             case 'D' :    /* downloading */
  985.                 break;
  986.             case 'U' :    /* uploading */
  987.                 break;
  988.             default :
  989.                 send_failure('N');
  990.                 return;
  991.             }
  992.  
  993.             switch(r_buffer[2])
  994.             {
  995.             case 'A':    /* ascii file */
  996.                 break;
  997.             case 'B':    /* binary file */
  998.                 break;
  999.             default :
  1000.                 send_failure('N');    /* not implemented */
  1001.                 return;
  1002.             }
  1003.  
  1004.             i=2;
  1005.             pt=filename;
  1006.             while((r_buffer[i]!=0)&&(i<r_size-1))
  1007.                 *pt++=r_buffer[++i];
  1008.  
  1009.             *pt='\0';
  1010.  
  1011.             if(r_buffer[1]=='U')
  1012.                 i=send_file(filename);
  1013.             else
  1014.                 i=receive_file(filename);
  1015.  
  1016.             sput("\r\n");
  1017.             if(i)
  1018.                 sput("\r\nTransfer successfully completed!\r\n");
  1019.             break;
  1020.  
  1021.         case '+':    /* Received Transport Parameters Packet */
  1022.             do_transport_parameters();
  1023.             break;
  1024.  
  1025.         case '?':    /* Received Application Parameters Packet */
  1026.             do_application_parameters();
  1027.             break;
  1028.  
  1029.         default:    /* Unknown packet; tell host we don't know */
  1030.             send_failure('N');
  1031.                 break;
  1032.  
  1033.         }  /* of case */
  1034.     }    /* of if read_packet the */
  1035. }
  1036.  
  1037.  
  1038.